home *** CD-ROM | disk | FTP | other *** search
- #
-
- /*LINTLIBRARY*/
-
- #ifndef lint
- #ifndef NOID
- static char sccsid[] = "@(#)timemk.c 3.2";
- #endif /* !NOID */
- #endif /* !lint */
-
- #ifdef STD_INSPIRED
-
- /*
- ** Code provided by Robert Elz, who writes:
- ** The "best" way to do mktime I think is based on an idea of Bob
- ** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
- ** It does a binary search of the time_t space. Since time_t's are
- ** just 32 bits, its a max of 32 iterations (even at 64 bits it
- ** would still be very reasonable).
- **
- ** This code does handle "out of bounds" values in the way described
- ** for "mktime" in the October, 1986 draft of the proposed ANSI C Standard;
- ** though this is an accident of the implementation and *cannot* be made to
- ** work correctly for the purposes there described.
- **
- ** A warning applies if you try to use these functions with a version of
- ** "localtime" that has overflow problems (such as System V Release 2.0
- ** or 4.3 BSD localtime).
- ** If you're not using GMT and feed a value to localtime
- ** that's near the minimum (or maximum) possible time_t value, localtime
- ** may return a struct that represents a time near the maximum (or minimum)
- ** possible time_t value (because of overflow). If such a returned struct tm
- ** is fed to timelocal, it will not return the value originally feed to
- ** localtime.
- */
-
- #include "time.h"
- #include "tzfile.h"
- #include "sys/types.h"
-
- #ifndef WRONG
- #define WRONG (-1)
- #endif /* !WRONG */
-
- extern struct tm * localtime();
- extern struct tm * gmtime();
- extern struct tm * offtime();
-
- static time_t
- timemk(timeptr, funcp, offset)
- struct tm * timeptr;
- struct tm * (* funcp)();
- long offset;
- {
- register int direction;
- register int bits;
- time_t t;
- struct tm yourtm, mytm;
-
- yourtm = *timeptr;
- /*
- ** Correct the tm supplied, in case some of its values are
- ** out of range.
- */
- while (yourtm.tm_sec >= SECS_PER_MIN)
- ++yourtm.tm_min, yourtm.tm_sec -= SECS_PER_MIN;
- while (yourtm.tm_sec < 0)
- --yourtm.tm_min, yourtm.tm_sec += SECS_PER_MIN;
- while (yourtm.tm_min >= MINS_PER_HOUR)
- ++yourtm.tm_hour, yourtm.tm_min -= MINS_PER_HOUR;
- while (yourtm.tm_min < 0)
- --yourtm.tm_hour, yourtm.tm_min += MINS_PER_HOUR;
- while (yourtm.tm_hour >= HOURS_PER_DAY)
- ++yourtm.tm_mday, yourtm.tm_hour -= HOURS_PER_DAY;
- while (yourtm.tm_hour < 0)
- --yourtm.tm_mday, yourtm.tm_hour += HOURS_PER_DAY;
- while (yourtm.tm_mday > 31) /* trust me [kre] */
- ++yourtm.tm_mon, yourtm.tm_mday -= 31;
- while (yourtm.tm_mday <= 0)
- --yourtm.tm_mon, yourtm.tm_mday += 31;
- while (yourtm.tm_mon >= MONS_PER_YEAR)
- ++yourtm.tm_year, yourtm.tm_mon -= MONS_PER_YEAR;
- while (yourtm.tm_mon < 0)
- --yourtm.tm_year, yourtm.tm_mon += MONS_PER_YEAR;
- /*
- ** Calcluate the number of magnitude bits in a time_t
- ** (this works regardless of whether time_t is
- ** signed or unsigned, though lint complains if unsigned).
- */
- for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
- ;
- /*
- ** If time_t is signed, then 0 is the median value,
- ** if time_t is unsigned, then 1 << bits is median.
- */
- t = (t < 0) ? 0 : ((time_t) 1 << bits);
- for ( ; ; ) {
- mytm = (funcp == offtime) ?
- *((*funcp)(&t, offset)) : *((*funcp)(&t));
- if ((direction = (mytm.tm_year - yourtm.tm_year)) == 0 &&
- (direction = (mytm.tm_mon - yourtm.tm_mon)) == 0 &&
- (direction = (mytm.tm_mday - yourtm.tm_mday)) == 0 &&
- (direction = (mytm.tm_hour - yourtm.tm_hour)) == 0 &&
- (direction = (mytm.tm_min - yourtm.tm_min)) == 0)
- direction = mytm.tm_sec - yourtm.tm_sec;
- if (direction == 0) {
- *timeptr = mytm;
- return t;
- }
- if (bits-- < 0) {
- *timeptr = yourtm; /* restore "original" value */
- if (yourtm.tm_mday == 31) {
- timeptr->tm_mday = 1;
- ++(timeptr->tm_mon);
- t = timemk(timeptr, funcp, offset);
- if (t != WRONG)
- return t;
- *timeptr = yourtm;
- } else if (yourtm.tm_mon == TM_FEBRUARY &&
- yourtm.tm_mday > 28) {
- timeptr->tm_mday -= 28;
- ++(timeptr->tm_mon);
- t = timemk(timeptr, funcp, offset);
- if (t != WRONG)
- return t;
- *timeptr = yourtm;
- }
- return WRONG;
- }
- if (bits < 0)
- --t;
- else if (direction > 0)
- t -= (time_t) 1 << bits;
- else t += (time_t) 1 << bits;
- }
- }
-
- time_t
- timelocal(timeptr)
- struct tm * timeptr;
- {
- return timemk(timeptr, localtime, 0L);
- }
-
- time_t
- timegm(timeptr)
- struct tm * timeptr;
- {
- return timemk(timeptr, gmtime, 0L);
- }
-
- time_t
- timeoff(timeptr, offset)
- struct tm * timeptr;
- long offset;
- {
- return timemk(timeptr, offtime, offset);
- }
-
- #endif /* STD_INSPIRED */
-